using System;

using OpenXmlWriter.Packaging;

namespace OpenXmlWriter.WordprocessingML.Packaging
{
  public class MainDocumentPart : OpenXmlPart
  {
    private const string PartRelationshipType =
      "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";

    private const string PartName = "document";
    private const string PartPath = "word";
    private const string PartExtension = ".xml";
    private string _internalContentType;
    private string _targetPath;

    public override void Initialize(OpenXmlPackage openXmlPackage, OpenXmlPartContainer openXmlPartContainer)
    {
      base.Initialize(openXmlPackage, openXmlPartContainer);
      _internalContentType = DetermineContentType();
      _targetPath = CreateUniquePath();

      _contentType = new ContentType(_targetPath, _internalContentType, false);
    }

    private string CreateUniquePath()
    {
      return PartPath + "/" + PartName + PartExtension;
    }

    private string DetermineContentType()
    {
      switch (((WordprocessingDocumentWriter) OpenXmlPackage).DocumentType)
      {
        case WordprocessingDocumentType.Template:
          return "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml";
        case WordprocessingDocumentType.Document:
        default:
          return "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
      }
    }

    public override void AddTo(OpenXmlPartCollection parts)
    {
      if (parts.ContainsKey(_targetPath))
      {
        throw new InvalidOperationException();
      }

      parts.Add(_targetPath, this);
    }

    public override string RelationshipType
    {
      get
      {
        return PartRelationshipType;
      }
    }

    public override ContentType ContentType
    {
      get
      {
        return _contentType;
      }
    }

    public override string TargetPath
    {
      get
      {
        return _targetPath;
      }
    }

    public HeaderPart AddHeaderPart()
    {
      return (HeaderPart) AddNewPart(typeof (HeaderPart));
    }

    public FooterPart AddFooterPart()
    {
      return (FooterPart) AddNewPart(typeof (FooterPart));
    }

    public StyleDefinitionsPart AddStyleDefinitionsPart()
    {
      return (StyleDefinitionsPart) AddNewPart(typeof (StyleDefinitionsPart));
    }

    public NumberingDefinitionsPart AddNumberingDefinitionsPart()
    {
      return (NumberingDefinitionsPart) AddNewPart(typeof (NumberingDefinitionsPart));
    }

    public EndnotesPart AddEndnotesPart()
    {
      return (EndnotesPart) AddNewPart(typeof (EndnotesPart));
    }

    public FontTablePart AddFontTablePart()
    {
      return (FontTablePart) AddNewPart(typeof (FontTablePart));
    }

    public CustomXmlPart AddCustomXmlPart()
    {
      return (CustomXmlPart) AddNewPart(typeof (CustomXmlPart));
    }

    public FootnotesPart AddFootnotesPart()
    {
      return (FootnotesPart) AddNewPart(typeof (FootnotesPart));
    }

    public ThemePart AddThemePart()
    {
      return (ThemePart) AddNewPart(typeof (ThemePart));
    }

    public DocumentSettingsPart AdddocumentSettingsPart()
    {
      return (DocumentSettingsPart) AddNewPart(typeof (DocumentSettingsPart));
    }

    public WebSettingsPart AddWebSettingsPart()
    {
      return (WebSettingsPart) AddNewPart(typeof (WebSettingsPart));
    }

    public CommentsPart AddCommentsPart()
    {
      return (CommentsPart) AddNewPart(typeof (CommentsPart));
    }

    public ImagePart AddImagePart(string fileName, string contentType)
    {
      ImagePart part = (ImagePart) Activator.CreateInstance(typeof (ImagePart), true);
      part.Initialize(_openXmlPackage, _openXmlPartContainer, fileName, contentType);
      part.AddTo(_parts);
      Relationship relationship = new Relationship(TargetPath, part.TargetPath, part.RelationshipType);
      part.Relationship = relationship;
      _relationships.Add(relationship);
      return part;
    }
  }
}